#include "Common.h"
#include "Shape.h"
#include "BoxShape.h"
#include "ShapeHelper.h"
#include "RenderView.h"
#include "SceneNode.h"
#include "Material.h"
#include "MaterialInstance.h"
#include "Mesh.h"
#include "MeshManager.h"
#include "VertexFactory.h"
#include "VertexIndexData.h"

const char* BoxShape::SHAPE_MESH_NAME = "Box";

Shape::Shape(const std::string& name, Scene* owner)
	: MovableObject(name, owner)
	, mEmissive(0, 0, 0)
	, mDiffuse(1, 1, 1)
	, mSpecular(0, 0, 0)
	, mMaterialInstance(NULL)
	, mMesh(NULL)
{
}

Shape::~Shape(void)
{
	if (mMaterialInstance != NULL)
		delete mMaterialInstance;
}

bool Shape::Init(const NameValeParamMap* params)
{
	if (!MovableObject::Init(params))
		return false;

	mMesh = MeshManager::Instance().GetByName(getShapeMeshName());
	if (mMesh == NULL)
		return false;
	
	mAABB = mMesh->getBounds();
	return true;
}

VertexFactory* Shape::getVertexFactory()
{
	return mMesh ? mMesh->getVertexFactory() : NULL;
}

MaterialInstance* Shape::getMaterial()
{
	if (mMaterialInstance == NULL)
	{
		mMaterialInstance = ShapeHelper::DefaultShapeMaterial()->CreateInstance();
		mEmissiveParamRef = mMaterialInstance->getMaterialParam().GetParamRef("EmissiveColor");
		mDiffuseParamRef = mMaterialInstance->getMaterialParam().GetParamRef("DiffuseColor");
		mSpecularParamRef = mMaterialInstance->getMaterialParam().GetParamRef("SpecularColor");

		ApplyColorChange();
	}
	return mMaterialInstance;
}

const IndexData* Shape::getIndexData() const
{
	return mMesh ? mMesh->GetSubMesh(0)->getIndexData() : NULL;
}

void Shape::AddToView(RenderView* view)
{
	view->AddRenderable(this);
}

void Shape::AddToScene()
{
	MovableObject::AddToScene();

	Renderable::AddToScene(mOwner);
}

void Shape::RemoveFromScene()
{
	MovableObject::RemoveFromScene();

	Renderable::RemoveFromScene(mOwner);
}

void Shape::UpdateTransform()
{
	MovableObject::UpdateTransform();
	
	// setup the world matrix.
	Renderable::setWorldMatrix(mParent->getCachedMatrix());
}

void Shape::ApplyColorChange()
{
	if (mMaterialInstance == NULL)
		return;

	mMaterialInstance->getMaterialParam().Set(mEmissiveParamRef, mEmissive);
	mMaterialInstance->getMaterialParam().Set(mDiffuseParamRef, mDiffuse);
	mMaterialInstance->getMaterialParam().Set(mSpecularParamRef, mSpecular);
}